package com.big.common.core.util;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.big.common.core.exception.CustomerException;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;

/**
 * <p>
 * 转换工具类
 * </p>
 *
 * @author 山归岿
 * @create 2025-06-21-15:18
 */
@Slf4j
public class ConvertUtil {

    /**
     * 将源对象列表转换为DTO列表
     *
     * @param tList    源对象列表
     * @param dtoClass DTO类
     * @param <T>      源对象类型
     * @return DTO列表
     */
    public static <T, R> List<R> convertList(List<T> tList, Class<R> dtoClass) {
        return convertList(tList, dtoClass, null);
    }

    /**
     * 将源对象列表转换为DTO列表
     *
     * @param tList    源对象列表
     * @param dtoClass DTO类
     * @param consumer 自定义设置逻辑
     * @param <T>      源对象类型
     * @return DTO列表
     */
    public static <T, R> List<R> convertList(List<T> tList, Class<R> dtoClass, Consumer<R> consumer) {
        Assert.notNull(tList, "源对象列表不能为 null");
        return tList.stream()
                .map(t -> convert(t, dtoClass, consumer))
                .toList();
    }

    /**
     * 将源对象转换为DTO
     *
     * @param t        源对象
     * @param dtoClass DTO类
     * @param consumer 自定义设置逻辑
     * @param <T>      源对象类型
     * @param <DTO>    DTO类型
     * @return DTO对象
     * @throws CustomerException 源对象为null或实例化失败时抛出
     */
    public static <T, DTO> DTO convert(T t, Class<DTO> dtoClass, Consumer<DTO> consumer) {
        if (t == null) {
            return null;
        }
        Assert.notNull(dtoClass, "DTO 类不能为 null");

        try {
            DTO dto = dtoClass.getDeclaredConstructor().newInstance();
            BeanUtil.copyProperties(t, dto);
            Optional.ofNullable(consumer).ifPresent(c -> c.accept(dto));
            return dto;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            log.error("DTO 创建失败: {}", dtoClass.getName(), e);
            throw new CustomerException("DTO 实例化失败: " + dtoClass.getName());
        }
    }

    /**
     * 将指定类型的对象转换为另一个指定类型的对象
     *
     * @param t        要转换的源对象
     * @param dtoClass 目标类型的Class对象，表示要转换到的类型
     * @param <T>      源对象的类型
     * @param <DTO>    目标对象的类型
     * @return 返回转换后的目标类型对象
     */
    public static <T, DTO> DTO convert(T t, Class<DTO> dtoClass) {
        return convert(t, dtoClass, null);
    }

}


